<?php
/**
 * @package pmapi
 * @copyright Copyright (c)2014 Enrico Fagnoni
 * @license GNU General Public License version 3, or later
 *
 * @since 1.0.0
 */
 
defined('_JEXEC') or die;

if (!class_exists('LinkedDataView')) require(JPATH_COMPONENT.DS.'views'.DS.'linkeddata.php');

/**
 * This view is strongly inspired on W3C's Linked Data Platform Paging specifications .
 * Here are some imported definitions:
 *  Paged resource
 *      A resource  whose representation may be too large to fit in a single HTTP response, 
 *      for which a server offers a sequence of single-page resources. A paged P is broken into 
 *      a sequence of pages (single-page resources) P1, P2, ...,Pn, the representation of each Pi 
 *      contains a subset of  P..
 *   Single-page resource
 *      One of a sequence of related resources P1, P2, ...,Pn, each of which contains a subset of 
 *      the state of another resource P. P is called the paged resource. For readers familiar with 
 *      paged feeds, a single-page resource is similar to a feed document and the same coherency/completeness 
 *      considerations apply.
 */
abstract class PagedLinkedDataView extends LinkedDataView
{
        
    public function isSinglePageResource()
    {
        $jinput = JFactory::getApplication()->input;
        return ( !is_null($jinput->get('start',null )) || !is_null($jinput->get('limit',null )));
    }
    
    public function inFirstPage()
    {
        return ( JFactory::getApplication()->input->get('start',0 )==0);
    }


    /**
     * If the requested uri is not a Single-Page Resource but it need pagination, 
     *  start a server side initiated page management redirecting to to first Single-Page Resource
     */  
    public function display($tpl = null) 
    {
        list($start,$limit) = $this->_getPageRequirement(null);

        $pageData = $this->get('Pagination')->getData();
        if (!$this->isSinglePageResource() && $pageData->next->link){
            // Server side initiated page management is need: redirect to first single page uri
            JFactory::getApplication()->redirect($this->getSinglePageURI()); 
        } else {       
            // create web links according to Linked Data Pagination specification..
            if ($link = $pageData->next->link) {
                ApiHelper::setHttpLink( $link,'next');
            }
            
            // last and first are optional in LDP paging specs... anyway they do not hurts...
            if ($start > 0) {
                $firstPageURI = $this->getPagedURI().self::_mkQueryString(array(0,$limit));
                ApiHelper::setHttpLink($firstPageURI,'first');
            }
            
            if ($pageData->next->link && $link = $pageData->end->link) {
                ApiHelper::setHttpLink($link,'last');
            }
            
            parent::display($tpl);  
        }
    }


    private static function _getPageRequirement()
    {
        $jinput = JFactory::getApplication()->input;
        return array( 
            $jinput->get('start',0, 'uint' ),
            $jinput->get('limit',JComponentHelper::getParams('com_pmapi')->get('page_limit',1000),'uint' )
        );
    }


    private static function _mkQueryString(array $pageRequirement)
    {
        $query ='';
        list($start,$limit) = $pageRequirement;
        if (!is_null($limit)) $query .= '?limit='.$limit;   
        if (!is_null($start)) $query .= '&start='.$start;
        
        return $query;     
    }
            
        
    public function getURI($forcePageZero=false) // $forcePageZero=false the uri as called by agent
    {      
        return parent::getURI().self::_mkQueryString(self::_getPageRequirement($forcePageZero));
    }
    
    
    public function getSinglePageURI() // i.e. the uri always with page info
    {      
        return $this->getURI(true);
    }


    public function getPagedURI()  // i.e. the uri withowut any page info.
    {
        return parent::getURI();
    } 
}